package com.linking.config.pojo;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.google.common.collect.Lists;
import java.util.List;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;

/**
 * @Author YaoWeiXin
 * @Date 2019/12/5 15:46
 * @Description 本身配置参数
 */
@Data
public class SelfConfigBO {

  /**
   * Redis 配置信息
   */
  private RedisConfigBO redisConfigBO;
  /**
   * Mongo 配置信息
   */
  private MongoConfigBO mongoConfigBo;
  /**
   * MQ 配置信息
   */
  private MqConfigBO mqConfigBo;
  /**
   * 阿里邮箱 配置信息
   */
  private AliMailConfigBO aliMailConfigBo;
  /**
   * netty 配置信息
   */
  private NettyConfigBO nettyConfigBo;
  /**
   * mysql 配置信息
   */
  private MysqlConfigBO mysqlConfigBo;
  /**
   * 阿里日志服务 配置信息
   */
  private LogHubConfigBO logHubConfigBo;


  public static SelfConfigBO of(String content) {
    JSONObject defaultJson = new JSONObject();
    SelfConfigBO bo = new SelfConfigBO();
    bo.setRedisConfigBO(RedisConfigBO.of(defaultJson));
    bo.setMongoConfigBo(MongoConfigBO.of(defaultJson));
    bo.setMqConfigBo(MqConfigBO.of(defaultJson));
    bo.setAliMailConfigBo(AliMailConfigBO.of(defaultJson));
    bo.setNettyConfigBo(NettyConfigBO.of(defaultJson));
    bo.setMysqlConfigBo(MysqlConfigBO.of(defaultJson));
    bo.setLogHubConfigBo(LogHubConfigBO.of(defaultJson));
    if (StringUtils.isNotEmpty(content)) {
      JSONObject config = JSON.parseObject(content);
      bo.setRedisConfigBO(RedisConfigBO.of(config));
      bo.setMongoConfigBo(MongoConfigBO.of(config));
      bo.setMqConfigBo(MqConfigBO.of(config));
      bo.setAliMailConfigBo(AliMailConfigBO.of(config));
      bo.setNettyConfigBo(NettyConfigBO.of(config));
      bo.setMysqlConfigBo(MysqlConfigBO.of(config));
      bo.setLogHubConfigBo(LogHubConfigBO.of(config));
    }
    return bo;
  }

  @Data
  public static class RedisConfigBO {

    /**
     * 最大连接数
     */
    private Integer maxActive;
    /**
     * 最大等待时间
     */
    private Integer maxWait;
    /**
     * 最大空闲
     */
    private Integer maxIdle;
    /**
     * 数据库配置集合
     */
    private List<RedisConfig> configs;

    private static RedisConfigBO of(JSONObject config) {
      RedisConfigBO bo = new RedisConfigBO();
      bo.setConfigs(Lists.newArrayList());
      String key = "redis";
      if (config.containsKey(key)) {
        JSONObject subConfig = config.getJSONObject(key);
        JSONArray dbList = subConfig.getJSONArray("db");
        int size = dbList.size();
        for (int i = 0; i < size; i++) {
          bo.getConfigs().add(RedisConfig.of(dbList.getJSONObject(i)));
        }
        bo.setMaxActive(config.containsKey("max-active") ? config.getInteger("max-active") : 10);
        bo.setMaxWait(config.containsKey("max-wait") ? config.getInteger("max-wait") : 10);
        bo.setMaxIdle(config.containsKey("max-idle") ? config.getInteger("max-idle") : 1);
      }
      return bo;
    }

    @Data
    public static class RedisConfig {

      /**
       * 连接名
       */
      private String name;
      /**
       * 地址
       */
      private String host;
      /**
       * 端口
       */
      private Integer port;
      /**
       * 密码
       */
      private String pwd;
      /**
       * 数据库
       */
      private Integer db;

      private static RedisConfig of(JSONObject config) {
        RedisConfig bo = new RedisConfig();
        bo.setHost(config.containsKey("name") ? config.getString("name") : "Primary");
        bo.setHost(config.containsKey("host") ? config.getString("host") : "127.0.0.1");
        bo.setPort(config.containsKey("port") ? config.getInteger("port") : 6379);
        bo.setPwd(config.containsKey("pwd") ? config.getString("pwd") : "");
        bo.setDb(config.containsKey("db") ? config.getInteger("db") : 0);
        return bo;
      }
    }
  }

  @Data
  public static class MongoConfigBO {

    /**
     * 数据库配置集合
     */
    private List<MongoConfig> configs;

    private static MongoConfigBO of(JSONObject config) {
      MongoConfigBO bo = new MongoConfigBO();
      bo.setConfigs(Lists.newArrayList());
      String key = "mongo";
      if (config.containsKey(key)) {
        JSONObject subConfig = config.getJSONObject(key);
        JSONArray dbList = subConfig.getJSONArray("db");
        int size = dbList.size();
        for (int i = 0; i < size; i++) {
          bo.getConfigs().add(MongoConfig.of(dbList.getJSONObject(i)));
        }
      }
      return bo;
    }

    @Data
    public static class MongoConfig {

      /**
       * 连接名
       */
      private String name;
      /**
       * 地址字符串
       */
      private String hostStr;
      /**
       * 地址集合
       */
      private List<String> hosts;
      /**
       * 端口集合
       */
      private List<Integer> ports;
      /**
       * 用户名
       */
      private String user;
      /**
       * 密码
       */
      private String pwd;
      /**
       * 授权数据库
       */
      private String authDb;
      /**
       * 默认数据库名
       */
      private String db;

      private static MongoConfig of(JSONObject config) {
        MongoConfig bo = new MongoConfig();
        bo.setHosts(Lists.newArrayList());
        bo.setPorts(Lists.newArrayList());
        bo.setHostStr("");
        String hosts = "hosts";
        String ports = "ports";
        if (config.containsKey(hosts) && config.containsKey(ports)) {
          JSONArray hostList = config.getJSONArray(hosts);
          JSONArray portList = config.getJSONArray(ports);
          for (int i = 0; i < hostList.size(); i++) {
            bo.getHosts().add(hostList.getString(i));
            bo.getPorts().add(portList.getIntValue(i));
            bo.setHostStr(bo.getHostStr() + hostList.getString(i));
          }
        }
        bo.setName(config.containsKey("name") ? config.getString("name") : "Primary");
        bo.setUser(config.containsKey("user") ? config.getString("user") : "root");
        bo.setPwd(config.containsKey("pwd") ? config.getString("pwd") : "root");
        bo.setAuthDb(config.containsKey("auth_db") ? config.getString("auth_db") : "admin");
        bo.setDb(config.containsKey("db") ? config.getString("db") : "db_");
        return bo;
      }
    }
  }

  @Data
  public static class MysqlConfigBO {

    /**
     * 数据库配置集合
     */
    private List<MysqlConfig> configs;

    private static MysqlConfigBO of(JSONObject config) {
      MysqlConfigBO bo = new MysqlConfigBO();
      bo.setConfigs(Lists.newArrayList());
      String key = "mysql";
      if (config.containsKey(key)) {
        JSONObject subConfig = config.getJSONObject(key);
        JSONArray dbList = subConfig.getJSONArray("db");
        int size = dbList.size();
        for (int i = 0; i < size; i++) {
          bo.getConfigs().add(MysqlConfig.of(dbList.getJSONObject(i)));
        }
      }
      return bo;
    }

    @Data
    public static class MysqlConfig {

      /**
       * 连接名
       */
      private String name;
      /**
       * 连接地址
       */
      private String url;
      /**
       * 用户名
       */
      private String user;
      /**
       * 密码
       */
      private String pwd;
      /**
       * driverClass
       */
      private String driverClassName;
      /**
       * 默认数据库名
       */
      private String db;

      private static MysqlConfig of(JSONObject config) {
        MysqlConfig bo = new MysqlConfig();
        bo.setName(config.containsKey("name") ? config.getString("name") : "Primary");
        bo.setUrl(config.containsKey("url") ? config.getString("url") : "jdbc:mysql://127.0.0.1:3306/db_test?useUnicode=true&characterEncoding=utf-8&useSSL=false&serverTimezone=GMT%2B8&connectTimeout=1000&socketTimeout=3000&autoReconnect=true");
        bo.setUser(config.containsKey("user") ? config.getString("user") : "root");
        bo.setPwd(config.containsKey("pwd") ? config.getString("pwd") : "root");
        bo.setDriverClassName(config.containsKey("driver-class-name") ? config.getString("driver-class-name") : "com.mysql.cj.jdbc.Driver");
        bo.setDb(config.containsKey("db") ? config.getString("db") : "db_");
        return bo;
      }
    }
  }

  @Data
  public static class MqConfigBO {

    /**
     * MQ地址
     */
    private String nameSrvAddr;
    /**
     * MQ组编号
     */
    private String groupId;
    /**
     * MQ访问编号
     */
    private String accessId;
    /**
     * MQ访问秘钥
     */
    private String accessSecret;

    private static MqConfigBO of(JSONObject config) {
      MqConfigBO bo = new MqConfigBO();
      String key = "mq";
      if (config.containsKey(key)) {
        JSONObject subConfig = config.getJSONObject(key);
        bo.setNameSrvAddr(
            subConfig.containsKey("addr") ? subConfig.getString("addr") : "127.0.0.1");
        bo.setGroupId(
            subConfig.containsKey("group_id") ? subConfig.getString("group_id") : "test");
        bo.setAccessId(
            subConfig.containsKey("access_id") ? subConfig.getString("access_id") : "test");
        bo.setAccessSecret(
            subConfig.containsKey("access_secret") ? subConfig.getString("access_secret") : "test");
      }
      return bo;
    }
  }

  @Data
  public static class AliMailConfigBO {

    /**
     * 邮箱地域
     */
    private String region;
    /**
     * 邮箱访问编号
     */
    private String accessId;
    /**
     * 邮箱访问秘钥
     */
    private String accessSecret;
    /**
     * 邮箱发信地址
     */
    private String account;
    /**
     * 邮箱发信昵称
     */
    private String alias;
    /**
     * 邮箱标签
     */
    private String tag;

    public Boolean testChinaRegion() {
      return "cn-hangzhou".equals(region);
    }

    private static AliMailConfigBO of(JSONObject config) {
      AliMailConfigBO bo = new AliMailConfigBO();
      String key = "aliMail";
      if (config.containsKey(key)) {
        JSONObject subConfig = config.getJSONObject(key);
        bo.setRegion(subConfig.containsKey("region") ? subConfig.getString("region") : "127.0.0.1");
        bo.setAccessId(subConfig.containsKey("access_id") ? subConfig.getString("access_id") : "test");
        bo.setAccessSecret(
            subConfig.containsKey("access_secret") ? subConfig.getString("access_secret") : "test");
        bo.setAccount(subConfig.containsKey("account") ? subConfig.getString("account") : "test");
        bo.setAlias(subConfig.containsKey("alias") ? subConfig.getString("alias") : "test");
        bo.setTag(subConfig.containsKey("tag") ? subConfig.getString("tag") : "test");
      }
      return bo;
    }
  }

  @Data
  public static class NettyConfigBO {

    /**
     * netty监听地址
     */
    private String host;
    /**
     * netty监听端口
     */
    private Integer port;
    /**
     * netty boss 线程数
     */
    private Integer bossThread;
    /**
     * netty worker 线程数
     */
    private Integer workerThread;
    /**
     * netty 业务线程数
     */
    private Integer businessThread;
    /**
     * netty 资源泄漏探测器 等级
     */
    private String leakDetectorLevel;
    /**
     * netty 最大负载大小
     */
    private Integer maxPayloadSize;

    private static NettyConfigBO of(JSONObject config) {
      NettyConfigBO bo = new NettyConfigBO();
      String key = "netty";
      if (config.containsKey(key)) {

        JSONObject subConfig = config.getJSONObject(key);
        String hostKey = "host";
        String portKey = "port";
        String btKey = "boss_thread";
        String wtKey = "worker_thread";
        String bstKey = "business_thread";
        String ldlKey = "leak_detector_level";
        String mpsKey = "max_payload_size";
        bo.setHost(subConfig.containsKey(hostKey) ? subConfig.getString(hostKey) : "127.0.0.1");
        bo.setPort(subConfig.containsKey(portKey) ? subConfig.getInteger(portKey) : 9876);
        bo.setBossThread(subConfig.containsKey(btKey) ? subConfig.getInteger(btKey) : 2);
        bo.setWorkerThread(subConfig.containsKey(wtKey) ? subConfig.getInteger(wtKey) : 4);
        bo.setBusinessThread(subConfig.containsKey(bstKey) ? subConfig.getInteger(bstKey) : 4);
        bo.setLeakDetectorLevel(subConfig.containsKey(ldlKey) ? subConfig.getString(ldlKey) : "DISABLED");
        bo.setMaxPayloadSize(subConfig.containsKey(mpsKey) ? subConfig.getInteger(mpsKey) : 65536);
      }
      return bo;
    }
  }

  @Data
  public static class LogHubConfigBO {
    /**
     * 日志服务区域
     */
    private String endpoint;
    /**
     * 日志服务访问ID
     */
    private String accessId;
    /**
     * 日志服务访问KEY
     */
    private String accessKey;
    /**
     * 组
     */
    private String group;
    /**
     * 日志服务配置集合
     */
    private List<LogHubConfig> configs;

    private static LogHubConfigBO of(JSONObject config) {
      LogHubConfigBO bo = new LogHubConfigBO();
      bo.setConfigs(Lists.newArrayList());
      String key = "log_hub";
      if (config.containsKey(key)) {
        JSONObject subConfig = config.getJSONObject(key);
        String endpointKey = "endpoint";
        String accessIdKey = "access_id";
        String accessKey = "access_key";
        bo.setEndpoint(subConfig.containsKey(endpointKey) ? subConfig.getString(endpointKey) : "");
        bo.setAccessId(subConfig.containsKey(accessIdKey) ? subConfig.getString(accessIdKey) : "");
        bo.setAccessKey(subConfig.containsKey(accessKey) ? subConfig.getString(accessKey) : "");
        bo.setGroup(subConfig.containsKey("group") ? subConfig.getString("group") : "default");

        JSONArray logHubList = subConfig.getJSONArray("consumers");
        int size = logHubList.size();
        for (int i = 0; i < size; i++) {
          bo.getConfigs().add(LogHubConfig.of(logHubList.getString(i)));
        }
      }
      return bo;
    }

    @Data
    public static class LogHubConfig {

      /**
       * 项目名
       */
      private String project;
      /**
       * 日志库
       */
      private String logStore;
      /**
       * 消费开始时间 大于0=使用秒数时间戳 等于-1则使用开始节点
       */
      private Integer startTimestamp;

      private static LogHubConfig of(String config) {
        LogHubConfig bo = new LogHubConfig();
        String[] temp = config.split(":");
        bo.setProject(temp[0]);
        bo.setLogStore(temp[1]);
        bo.setStartTimestamp(Integer.parseInt(temp[2]));
        return bo;
      }
    }
  }
}
